package org.spring.bean.factory.support;

import com.sun.istack.internal.Nullable;
import org.spring.bean.exceptions.BeanDefinitionStoreException;
import org.spring.core.io.Resource;
import org.spring.core.io.ResourceLoader;

/**
 * bean 定义阅读器的简单界面。使用资源和字符串位置参数指定加载方法。
 *
 * <p>具体的 bean 定义阅读器当然可以为 bean 定义添加额外的加载和注册方法，特定于它们的 bean 定义格式。
 *
 * <p>请注意，bean 定义阅读器不必实现此接口。它仅作为对希望遵循标准命名约定的 bean 定义读者的建议。
 *
 * @author 李坤
 * @date 2022/4/23 12:43
 */
public interface BeanDefinitionReader {

    /**
     * 返回用于 bean 类的类加载器。
     * <p>
     * 建议不要急切地加载 bean 类，而只是用类名注册 bean 定义，并在以后（或永远不会）解析相应的类。
     */
    @Nullable
    ClassLoader getClassLoader();

    /**
     * 返回 bean 工厂以注册 bean 定义。
     * <p>
     * 工厂通过 BeanDefinitionRegistry 接口公开，封装了与 bean 定义处理相关的方法。
     */
    BeanDefinitionRegistry getBeanDefinitionRegistry();

    /**
     * 返回资源加载器以用于资源位置。
     * 可以检查 <b>ResourcePatternResolver<b> 接口并进行相应的转换，以便为给定的资源模式加载多个资源。
     * <p>{@code null} 返回值表明绝对资源加载不适用于此 bean 定义阅读器。
     * <p>这主要用于从 bean 定义资源中导入更多资源，例如通过 XML bean 定义中的“import”标签。
     * 但是，建议相对于定义资源应用此类导入；只有明确的完整资源位置才会触发绝对资源加载。
     * <p>还有一个 {@code loadBeanDefinitions(String)} 方法可用，用于从资源位置（或位置模式）加载 bean 定义。
     * 这是避免显式 ResourceLoader 处理的便利。
     *
     * @see #loadBeanDefinitions(String)
     */
    ResourceLoader getResourceLoader();


    /**
     * 从指定资源加载 bean 定义。
     *
     * @param resource 资源描述符
     *
     * @return 找到的 bean 定义的数量
     *
     * @throws BeanDefinitionStoreException 在加载或解析错误的情况下
     */
    int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;

    /**
     * 从指定资源加载 bean 定义。
     *
     * @param resources 资源描述符
     *
     * @return 找到的 bean 定义的数量
     *
     * @throws BeanDefinitionStoreException 在加载或解析错误的情况下
     */
    int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;

    /**
     * 从指定的资源位置加载 bean 定义。
     * <p>位置也可以是位置模式，前提是此 bean 定义读取器的 ResourceLoader 是 ResourcePatternResolver。
     *
     * @param location 资源位置，将使用此 bean 定义阅读器的 ResourceLoader（或 ResourcePatternResolver）加载
     *
     * @return 找到的 bean 定义的数量
     *
     * @throws BeanDefinitionStoreException 在加载或解析错误的情况下
     * @see #getResourceLoader()
     * @see #loadBeanDefinitions(Resource)
     * @see #loadBeanDefinitions(Resource[])
     */
    int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;

    /**
     * 从指定的资源位置加载 bean 定义。
     *
     * @param locations 资源位置，将使用此 bean 定义阅读器的 ResourceLoader（或 ResourcePatternResolver）加载
     *
     * @return 找到的 bean 定义的数量
     *
     * @throws BeanDefinitionStoreException 在加载或解析错误的情况下
     */
    int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;

}
